var aGoods = {
  pic: '.',
  title: '..',
  desc: `...`,
  sellNumber: 1,
  favorRate: 2,
  price: 3
}

class UIGoods {
  constructor (g) {
    // 冻结原始数据
    g = { ...g }
    Object.freeze(g)
    Object.defineProperty(this, 'data', {
      // value: g,
      // writable: false,
      configurable: false,
      get: function () {
        return g
      },
      set: function () {
        throw new Error('data 属性是只读的，不能重新赋值')
      }
    })

    var internalChooseValue = 0
    Object.defineProperty(this, 'choose', {
      configurable: false,
      get: function () {
        return internalChooseValue
      },
      // 如果要给他赋值，可以在这里添加任意的规则判断
      set: function (val) {
        if (typeof val !== 'number') {
          throw new Error('choose属性必须是数字')
        }
        var temp = parseInt(val)
        if (temp !== val) {
          throw new Error('choose属性必须是整数')
        }
        if (val < 0) {
          throw new Error('choose属性必须大于等于 0')
        }
        internalChooseValue = val
      }
    })

    // Object.seal() 方法封闭一个对象，阻止添加新属性并将所有现有属性标记为不可配置。
    // 当前属性的值只要原来是可写的就可以改变
    // 写在这里证明不能在构造函数上添加属性，但是还可以在外面添加方法
    this.a = 1
    Object.seal(this)
  }
  // 一个简化的写法，只有get,相当于属性描述符中只有get
  get totalPrice () {
    return this.choose * this.data.price
  }

  get isChoose () {
    return this.choose > 0
  }
}
// 冻结构造函数的属性，不能任意添加属性和方法，完全冻结
Object.freeze(UIGoods.prototype)

let g = new UIGoods(aGoods)
// g.data.price=100
// g.data = 'abc'
console.log(g)
